package com.jrx.anytxn.param.service.product.impl;

import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.jrx.anytxn.common.data.TxnRespCode;
import com.jrx.anytxn.common.exception.TxnBizException;
import com.jrx.anytxn.common.exception.TxnException;
import com.jrx.anytxn.common.uitl.BeanMapping;
import com.jrx.anytxn.common.uitl.StringUtils;
import com.jrx.anytxn.i18n.response.TxnPage;
import com.jrx.anytxn.number.exception.SegmentException;
import com.jrx.anytxn.number.service.ISegmentService;
import com.jrx.anytxn.param.constant.Constant;
import com.jrx.anytxn.param.constant.ErrorMsgConstant;
import com.jrx.anytxn.param.dto.aviator.RuleMatchReq;
import com.jrx.anytxn.param.dto.product.ProductTableReq;
import com.jrx.anytxn.param.dto.product.ProductTableRes;
import com.jrx.anytxn.param.entity.PrProductFund;
import com.jrx.anytxn.param.entity.PrProductTable;
import com.jrx.anytxn.param.mapper.ext.ExtPrProductFundMapper;
import com.jrx.anytxn.param.mapper.ext.ExtPrProductTableMapper;
import com.jrx.anytxn.param.service.aviator.IAviatorService;
import com.jrx.anytxn.param.service.product.IProductTableService;
import org.apache.commons.collections.CollectionUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheConfig;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.*;

/**
 * 产品表 业务接口实现
 *
 * @author 黄秋平
 * @date 2020-5-26 15:30:13
 */
@Service
@CacheConfig(cacheNames = "PRODUCT")
public class ProductTableServiceImpl implements IProductTableService {

    private static final Logger logger = LoggerFactory.getLogger(ProductTableServiceImpl.class);

    @Resource
    private ExtPrProductTableMapper extPrProductTableMapper;

    @Resource
    private ExtPrProductFundMapper extPrProductFundMapper;

    @Resource
    private ISegmentService segmentService;

    @Autowired
    private IAviatorService aviatorService;

    @Override
    public TxnPage<ProductTableRes> findAllPageByTenId(Integer pageNum, Integer pageSize, String tenantId) throws TxnException {
        Page<PrProductTable> page = PageHelper.startPage(pageNum, pageSize,Constant.ORDER_BY_SORT);
        List<PrProductTable> productTableList = extPrProductTableMapper.selectByTenId(tenantId,null);
        if (productTableList.isEmpty()) {
            logger.error(TxnRespCode.NO_DATA.getMsg());
            throw new TxnException(TxnRespCode.NO_DATA.getMsg());
        }
        List<ProductTableRes> res = BeanMapping.copyList(productTableList, ProductTableRes.class);
        return new TxnPage<>(pageNum, pageSize, page.getTotal(), res);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public ProductTableRes addProductTable(ProductTableReq productTableReq) throws TxnException {
        if (productTableReq.getMaxAmount() != null && productTableReq.getMinAmount() != null && productTableReq.getMaxAmount().compareTo(productTableReq.getMinAmount()) < 0) {
            throw new TxnBizException(TxnRespCode.BIZ_ERROR.getCode(), "输入有误,最大金额要比最小金额大");
        }
        PrProductTable productTable = BeanMapping.copy(productTableReq, PrProductTable.class);
        PrProductTable prProductTable = extPrProductTableMapper.selectProductByProductId(productTable.getProductId(),productTable.getTenantId());
        if (prProductTable != null) {
            logger.error(TxnRespCode.DATA_EXISTS.getMsg());
            throw new TxnException(TxnRespCode.DATA_EXISTS.getMsg());
        }
        /*查看此产品下的资金源id是否相同*/
        List<PrProductFund> productFunds = productTableReq.getCon();
        Set<PrProductFund> set = new TreeSet<>((o1, o2) -> {
            //==0表示重复
            int compareToResult = 1;
            if (o1.getFundId().equalsIgnoreCase(o2.getFundId())) {
                compareToResult = 0;
            }
            return compareToResult;
        });
        set.addAll(productFunds);
        if (new ArrayList<>(set).size() != productFunds.size()) {
            logger.error("资金源id重复");
            throw new TxnException("资金源id不能重复！");
        }

        //增加产品表信息
        try {
            productTable.setId(segmentService.getId(Constant.PR_PRODUCT_TABLE));
        } catch (SegmentException e) {
            logger.error("主键生成错误",e);
            throw new TxnException(ErrorMsgConstant.ERROR_ID);
        }
        productTable.setRecordVersionNumber(Constant.VERSION_NUMBER);
        extPrProductTableMapper.insertSelective(productTable);
        //增加产品资金源配置信息
        List<PrProductFund> list = productTableReq.getCon();
        if(productTableReq.getCon().size()==0&&productTableReq.getAllowJointFlag()!=null&&Integer.parseInt(productTableReq.getAllowJointFlag())==1){
            throw new TxnBizException(TxnRespCode.BIZ_ERROR.getCode(), "产品资金源未配置");
        }
        for (PrProductFund productFund : list) {
            try {
                productFund.setId(segmentService.getId(Constant.PR_PRODUCT_FUND));
            } catch (SegmentException e) {
                logger.error("主键生成错误", e);
                throw new TxnException(ErrorMsgConstant.ERROR_ID);
            }
            productFund.setTenantId(productTableReq.getTenantId());
            productFund.setUpdateBy(productTableReq.getUpdateBy());
            productFund.setProductId(productTableReq.getProductId());
            productFund.setOrganizationId(productTableReq.getOrganizationId());
            productFund.setRecordVersionNumber(Constant.VERSION_NUMBER);
            extPrProductFundMapper.insertSelective(productFund);
        }


        return BeanMapping.copy(productTable, ProductTableRes.class);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    @CacheEvict(key = "'product_'+#productTableReq.tenantId+'_'+#productTableReq.productId")
    public ProductTableRes modifyProductTable(ProductTableReq productTableReq) throws TxnException {
        if (productTableReq.getMaxAmount() != null && productTableReq.getMinAmount() != null && productTableReq.getMaxAmount().compareTo(productTableReq.getMinAmount()) < 0) {
            throw new TxnBizException(TxnRespCode.BIZ_ERROR.getCode(), "输入有误,最大金额要比最小金额大");
        }
        PrProductTable productTable = BeanMapping.copy(productTableReq, PrProductTable.class);
        PrProductTable prProductTable = extPrProductTableMapper.selectByTenIdAndProId(productTable.getTenantId(),productTable.getProductId());
        if (prProductTable == null) {
            logger.error(TxnRespCode.NO_DATA.getMsg());
            throw new TxnException(TxnRespCode.NO_DATA.getMsg());
        }
        /*查看此产品下的资金源id是否相同*/
        List<PrProductFund> productFunds = productTableReq.getCon();
        Set<PrProductFund> set = new TreeSet<>((o1, o2) -> {
            //==0表示重复
            int compareToResult = 1;
            if (o1.getFundId().equalsIgnoreCase(o2.getFundId())) {
                compareToResult = 0;
            }
            return compareToResult;
        });
        set.addAll(productFunds);
        if (new ArrayList<>(set).size() != productFunds.size()) {
            logger.error("资金源id重复");
            throw new TxnException("资金源id不能重复！");
        }
        // 更新产品表
        extPrProductTableMapper.updateByTenIdAndProId(productTable);
        // 更新产品资金源配置表（先删后加）
        PrProductFund prProductFund = new PrProductFund();
        prProductFund.setTenantId(productTable.getTenantId());
        prProductFund.setProductId(productTable.getProductId());
        List<PrProductFund> productFundList = extPrProductFundMapper.selectByProductIdAndTenId(prProductFund.getProductId(), prProductFund.getTenantId());
        if (productFundList != null && !productFundList.isEmpty()) {
            for (PrProductFund factorTable : productFundList) {
                extPrProductFundMapper.deleteByProductIdAndTenId(factorTable.getProductId(),factorTable.getTenantId());
            }
        }
        List<PrProductFund> list = productTableReq.getCon();
        if(productTableReq.getCon().size()==0&&productTableReq.getAllowJointFlag()!=null&&Integer.parseInt(productTableReq.getAllowJointFlag())==1){
            throw new TxnBizException(TxnRespCode.BIZ_ERROR.getCode(), "产品资金源未配置");
        }
        for (PrProductFund pr : list) {
            try {
                pr.setId(segmentService.getId(Constant.PR_PRODUCT_FUND));
            } catch (SegmentException e) {
                logger.error("主键生成错误", e);
                throw new TxnException(ErrorMsgConstant.ERROR_ID);
            }
            pr.setTenantId(productTable.getTenantId());
            pr.setProductId(productTable.getProductId());
            pr.setOrganizationId(productTable.getOrganizationId());
            pr.setUpdateBy(productTable.getUpdateBy());
            pr.setRecordVersionNumber(productTable.getRecordVersionNumber() == null ? 1 : productTable.getRecordVersionNumber());
            extPrProductFundMapper.insertSelective(pr);
        }

        return BeanMapping.copy(productTable, ProductTableRes.class);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    @CacheEvict(key = "'product_'+#tenantId+'_'+#productId")
    public Boolean removeByTenIdAndProId(String tenantId, String productId) throws TxnException {
        if (StringUtils.isBlank(tenantId) || StringUtils.isBlank(productId)) {
            logger.error(TxnRespCode.NOT_EMPTY.getMsg());
            throw new TxnException(TxnRespCode.NOT_EMPTY.getMsg());
        }
        /*根据租户ID和产品ID查询产品表信息*/
        PrProductTable prProductTable = extPrProductTableMapper.selectByTenIdAndProId(tenantId,productId);

        /*获取查询信息的产品ID和租户ID查询产品资金源配置表里的相关信息列表*/
        PrProductFund prProductFund = new PrProductFund();
        prProductFund.setTenantId(prProductTable.getTenantId());
        prProductFund.setProductId(prProductTable.getProductId());
        List<PrProductFund> list = extPrProductFundMapper.selectByProductIdAndTenId(prProductFund.getProductId(), prProductFund.getTenantId());
        if (list != null) {
            for (PrProductFund pr : list) {
                extPrProductFundMapper.deleteByProductIdAndTenId(pr.getProductId(), pr.getTenantId());
            }
        }

        int i = extPrProductTableMapper.deleteByTenIdAndProId(tenantId, productId);
        return i > 0;
    }

    @Override
    public ProductTableRes findByTenIdAndProId(String tenantId, String productId) throws TxnException {
        if (StringUtils.isBlank(tenantId) || StringUtils.isBlank(productId)) {
            logger.error(TxnRespCode.NOT_EMPTY.getMsg());
            throw new TxnException(TxnRespCode.NOT_EMPTY.getMsg());
        }
        /*根据租户ID和产品ID查询产品表信息*/
        PrProductTable productTable = extPrProductTableMapper.selectByTenIdAndProId(tenantId, productId);
        /*获取查询信息的产品ID和租户ID查询产品资金源配置表里的相关信息列表*/
        PrProductFund prProductFund = new PrProductFund();
        prProductFund.setTenantId(productTable.getTenantId());
        prProductFund.setProductId(productTable.getProductId());
        List<PrProductFund> list = extPrProductFundMapper.selectByProductIdAndTenId(prProductFund.getProductId(), prProductFund.getTenantId());
        ProductTableRes res = BeanMapping.copy(productTable, ProductTableRes.class);
        res.setCon(list);
        return res;
    }

    @Override
    public List<ProductTableRes> findAllProductByTenId(String tenantId) {
        List<PrProductTable> prProductTableList = extPrProductTableMapper.selectByTenId(tenantId,Constant.STATUS_1);
        return BeanMapping.copyList(prProductTableList, ProductTableRes.class);
    }

    @Override
    public List<ProductTableRes> findProductByOrgIdAndTenId(String orgId, String tenantId) throws TxnException {
        if (StringUtils.isBlank(orgId) || StringUtils.isBlank(tenantId)) {
            logger.error("额度节点机构号为空");
            throw new TxnException(TxnRespCode.NOT_EMPTY);
        }
        List<PrProductTable> productTableResList = extPrProductTableMapper.selectProductByOrgIdAndTenId(orgId, tenantId);
        return BeanMapping.copyList(productTableResList, ProductTableRes.class);
    }


    @Cacheable(key = "'product_'+#tenantId+'_'+#productId")
    @Override
    public PrProductTable findProByProIdAndOrgId(String productId, String orgId, String tenantId) throws TxnBizException {
        if (StringUtils.isBlank(productId)) {
            logger.error(TxnRespCode.NOT_EMPTY.getMsg());
            throw new TxnBizException(TxnRespCode.NOT_EMPTY.getCode(), TxnRespCode.NOT_EMPTY.getMsg(ErrorMsgConstant.PRODUCT_ID));
        }
        PrProductTable productTable = extPrProductTableMapper.selectByProductIdAndOrgIdAndStatus(productId, orgId, Constant.STATUS_1, tenantId);
        if (productTable == null) {
            throw new TxnBizException(TxnRespCode.NO_DATA.getCode(), TxnRespCode.NO_DATA.getMsg(ErrorMsgConstant.PRODUCT));
        }
        return productTable;
    }

    @Override
    public List<PrProductTable> findAllForBatch(String tableStatus) {
        List<PrProductTable> prProductTableList = extPrProductTableMapper.findAllForBatch(tableStatus);
        return prProductTableList;
    }

    @Override
    public List<PrProductTable> findAllVerifyForBatch(String tableStatus, String verifyFileFlag) {
        List<PrProductTable> prProductTableList = extPrProductTableMapper.findByVerifyFileFlag(tableStatus,verifyFileFlag);
        return prProductTableList;
    }

    /**
     * 根据产品id获取该产品下的资金源
     *
     * @param productId 产品id
     * @param tenantId 租户id
     * @return List<PrProductFund>
     */
    @Cacheable(key = "'productFund_'+#tenantId+'_'+#productId")
    @Override
    public List<PrProductFund> findFundByProductId(String productId, String tenantId) throws TxnBizException {
        if (StringUtils.isBlank(productId)) {
            logger.error(TxnRespCode.NOT_EMPTY.getMsg());
            throw new TxnBizException(TxnRespCode.NOT_EMPTY.getCode(), TxnRespCode.NOT_EMPTY.getMsg(ErrorMsgConstant.PRODUCT_ID));
        }
        List<PrProductFund> productFunds = extPrProductFundMapper.selectByProductIdAndTenId(productId, tenantId);
        if (CollectionUtils.isEmpty(productFunds)) {
            throw new TxnBizException(TxnRespCode.NO_DATA.getCode(), TxnRespCode.NO_DATA.getMsg(ErrorMsgConstant.PRODUCT));
        }
        return productFunds;
    }

    /**
     * 根据产品类型，渠道通过规则匹配产品
     * @param productType
     * @param tenantId
     * @param channel
     * @param orgId
     * @return
     * @throws TxnBizException
     */
    @Override
    public PrProductTable getPrProductTableByRule(String productType,String tenantId,String channel,String orgId) throws TxnBizException {
        Map<String, Object> map = new HashMap<>();
        map.put(Constant.LOAN_RULE_TRANS_CHANNEL, channel);
        map.put(Constant.LOAN_RULE_PRODUCT_TYPE, productType);
        RuleMatchReq ruleMatchReq = new RuleMatchReq(orgId, null, Constant.PRO_MATCH_RULE_TYPE, map,
                tenantId);
        String productId = aviatorService.executeRuleResultMap(ruleMatchReq).get(Constant.LOAN_RULE_RES_KEY).toString();
        return this.findProByProIdAndOrgId(productId,orgId,tenantId);
    }
}
